#!/usr/bin/python3
#-*-coding:utf-8-*-

###############################################################
## Name       : gen_ral_rand
## Author     : gaojiaming
## Date       : Fri Feb 17 15:16:23 CST 2023
## Description:
##
##
###############################################################

import sys
import os
import re
import argparse

class Field:
    def __init__(self, name, parent, default):
        self.name = name
        self.parent = parent
        self.default = default

    def add_block(self, block):
        self.block = block
pass

def analy_input_path(file_path):
    fpath, f_bck = os.path.splitext(file_path)
    f_name = os.path.basename(fpath)
    f_path = os.path.dirname(fpath)
    if f_path == "":
        f_path = "./"
    return f_path, f_name, f_bck
pass

def analysis_ral(file_path):
    field_list = []
    blk_name = ""
    with open(file_path, "r") as handle:
        hd = handle.readlines()
        reg_name = ""
        blk_name = ""
        for line in hd:
            res_uvm_reg = re.search(r"class (\w+) extends uvm_reg;", line)
            res_rw_field = re.search(r"this\.(\w+)\.configure\(this, \d+, \d+, \"RW\", \d+, (\d+'h\d+), \d+, \d+, \d+\);", line)
            res_uvm_block = re.search(r"class (\w+) extends uvm_reg_block;", line)
            if res_uvm_reg:
                reg_name = res_uvm_reg.group(1)
            elif res_rw_field:
                field_name = res_rw_field.group(1)
                field_default = res_rw_field.group(2)
                field_list.append(Field(field_name, reg_name, field_default))
            elif res_uvm_block:
                blk_name = res_uvm_block.group(1)
    for field in field_list:
        field.add_block(blk_name)
    return field_list, blk_name
pass

def gen_field_rand(field_list):
    field_cons_list = []
    for field in field_list:
        constraint = ""
        blk_name = re.sub("^ral_block_", "", field.block)
        reg_name = re.sub("^ral_reg_", "", field.parent)
        field_name = field.name
        
        reg_inst = re.search(r"{0}_(\w+)".format(blk_name), reg_name).group(1)
        field_inst = reg_inst + "_" + field_name
        field_cons = reg_inst + "_" + field_name + "_cons"
        #print(blk_name, reg_name, reg_inst, field_inst)
        constraint += "    this.{0}.value dist {{'0:/10, ['0:'1]:/80, '1:/10}}; //default: {1}\n".format(field_inst, field.default)
        #print(constraint)
        field_cons_list.append(constraint)
    return field_cons_list
pass

def gen_block_rand(field_cons_list, blk_name):
    str = "class rand_{0} extends {0};\n".format(blk_name)
    str+= "  function new(string name = \"rand_{0}\");\n".format(blk_name)
    str+= "    super.new(name);\n"
    str+= "  endfunction\n"
    str+= "  constraint field_value_cons{\n"

    for line in field_cons_list:
        str += line
    str+= "  }\n"    
    str += "  `uvm_object_utils(rand_{0})\nendclass: rand_{0}".format(blk_name)
    return str
pass

def main():
    in_file = sys.argv[1]
    f_path, f_name, f_bck = analy_input_path(in_file)
    field_list, blk_name = analysis_ral(in_file)
    field_cons_list = gen_field_rand(field_list)
    output_str = gen_block_rand(field_cons_list, blk_name)
    out_file = "{0}/rand_{1}.sv".format(f_path, f_name)
    with open(out_file, "w") as hd:
        hd.write(output_str)
pass

if __name__ == "__main__":
    main()
